package com.iscreen.utils.download;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;

import com.iscreen.utils.exceptions.IScreenException;
import com.iscreen.utils.exceptions.IScreenExceptionCodes;

public class FileDownloader
{

	private final static int BUFFER_SIZE = 4 * 1024;

	private static URL getSourceURL(String source) throws IScreenException
	{
		try
		{
			URL url = new URL(source);
			return url;
		}
		catch (MalformedURLException e)
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR, e);
		}
	}

	private static void createFile(File file) throws IScreenException
	{
		file.getParentFile().mkdirs();
		if (!file.getParentFile().exists())
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR,
					"Unable to create destination folder "
							+ file.getParentFile().getAbsolutePath() + " for file download.");
		}
		
		try
		{
			file.createNewFile();
		}
		catch (IOException e)
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR, e);
		}
	}

	private static File getTargetFile(String target) throws IScreenException
	{
		File file = new File(target);
		createFile(file);
		return file;
	}

	private static void copy(InputStream is, OutputStream os)
			throws IScreenException
	{
		BufferedInputStream input = new BufferedInputStream(is);
		BufferedOutputStream output = new BufferedOutputStream(os);

		try
		{
			byte[] buffer = new byte[BUFFER_SIZE];

			int bytesRead;
			while ((bytesRead = input.read(buffer)) != -1)
			{
				output.write(buffer, 0, bytesRead);
			}
		}
		catch (IOException e)
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR, e);
		}
		finally
		{
			if (input != null)
			{
				try
				{
					input.close();
				}
				catch (IOException e)
				{
					// TODO only log is needed here
					e.printStackTrace();
				}
			}
			if (output != null)
			{
				try
				{
					output.close();
				}
				catch (IOException e)
				{
					// TODO only log is needed here
					e.printStackTrace();
				}
			}
		}

	}

	private static void copy(URL sourceUrl, File targetFile)
			throws IScreenException
	{
		InputStream inputStream;
		try
		{
			inputStream = sourceUrl.openStream();
		}
		catch (IOException e)
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR, e);
		}
		OutputStream outputStream;
		try
		{
			outputStream = new FileOutputStream(targetFile);
		}
		catch (FileNotFoundException e)
		{
			throw new IScreenException(IScreenExceptionCodes.FILE_DOWNLOAD_ERROR, e);
		}

		copy(inputStream, outputStream);

	}

	public static void download(String source, String target)
			throws IScreenException
	{
		URL sourceUrl = getSourceURL(source);
		File targetFile = getTargetFile(target);
		copy(sourceUrl, targetFile);

	}
}
